package com.cashmama.market.api.application.controller.order;

import com.cashmama.market.api.application.controller.order.request.*;
import com.cashmama.market.api.application.controller.order.response.*;
import com.cashmama.market.api.domain.enums.MobikwikNetBankEnum;
import com.cashmama.market.api.domain.service.ApiProductService;
import com.cashmama.market.api.domain.service.OrderService;
import com.cashmama.market.api.domain.service.ProductService;
import com.cashmama.market.api.domain.vo.RequestLocalInfo;
import com.cashmama.market.api.domain.vo.order.*;
import com.cashmama.market.api.infras.config.ApolloConfigUtil;
import com.cashmama.market.api.infras.consts.RedisKeyConsts;
import com.cashmama.market.api.infras.consts.TimeConsts;
import com.cashmama.market.api.infras.enums.JumpRouterEnum;
import com.cashmama.market.api.infras.enums.error.OrderRestErrorEnum;
import com.cashmama.market.api.infras.enums.error.ProductErrorCodeEnum;
import com.cashmama.market.api.infras.exception.ApplicationException;
import com.cashmama.market.api.infras.handler.ApiResponse;
import com.cashmama.market.api.infras.utils.HttpUtil;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.api.Response;
import com.fqgj.common.api.annotations.ParamsValidate;
import com.qianli.cashmama.product.facade.ProductFacade;
import com.qianli.cashmama.product.facade.result.Product;
import com.qianli.cashmama.product.facade.result.ProductCategory;
import com.qianli.cashmama.trade.client.trade.TradeQueryService;
import com.qianli.cashmama.trade.client.trade.response.CreateTradeResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: market-api
 * @description 订单相关接口
 * @author: frank
 * @create: 2019-12-19 21:17
 **/
@RestController
@RequestMapping("/order")
public class OrderController {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);

    @Autowired
    private OrderService orderService;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private ProductFacade productFacade;
    @Autowired
    private ApolloConfigUtil apolloConfigUtil;
    @Autowired
    private ApiProductService apiProductService;


    @Autowired
    private TradeQueryService tradeQueryService;

    @Autowired
    private ProductService productService;

    /**
     * 订单确认详情
     *
     * @param orderConfirmRequest
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/submit/get", method = RequestMethod.POST)
    public ApiResponse<OrderConfirmDetailVO> orderConfirm(@RequestBody @Valid OrderConfirmRequest orderConfirmRequest) {
        OrderConfirmDetailVO orderConfirmDetailVO = orderService.orderConfirmInfo(orderConfirmRequest.getProductCode(), orderConfirmRequest.getMerchantCode());
        return new ApiResponse<>(orderConfirmDetailVO);
    }

    /**
     * 订单条件确认接口
     *
     * @param orderFilterRequest
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/submit/filter", method = RequestMethod.POST)
    public ApiResponse<OrderFilterResponse> submitFilter(@RequestBody @Valid OrderFilterRequest orderFilterRequest) {
        String mobile = RequestLocalInfo.getCurrentUser().getMobile();
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        OrderFilterResponse orderFilterResponse = new OrderFilterResponse();
        orderFilterResponse.setJumpUrl(JumpRouterEnum.PRODUCT_CONFIRM.getJumpUrl() + "?productCode=" + orderFilterRequest.getProductCode() + "&merchantCode=" + orderFilterRequest.getMerchantCode());
        orderFilterResponse.setMerchantCode(orderFilterRequest.getMerchantCode());
        if (apolloConfigUtil.auditMobiles().contains(mobile)) {
            return new ApiResponse<>(orderFilterResponse);
        }
        ProductCategory productCategory = apiProductService.getProductCategoryByMerchantCode(orderFilterRequest.getMerchantCode());
        if (productCategory == null) {
            throw new ApplicationException("merchant not exist, pls refresh");
        }


        int requestAppVersionCode = RequestLocalInfo.getRequestBasicInfo().getVersionCode();
        LOGGER.info("== 获取当前请求的版本号 ==,versionCode:{},basicParam:{}", requestAppVersionCode, RequestLocalInfo.getRequestBasicInfo());
        if (requestAppVersionCode == apolloConfigUtil.getAppNeedUpdateMinVersion()) {
            throw new ApplicationException(OrderRestErrorEnum.UPDATE_NOTE);
        }

        boolean quotaFull = productService.currentMerchantQuotaFull(userCode, mobile, productCategory);
        if (quotaFull) {
            throw new ApplicationException(OrderRestErrorEnum.APPLY_PERMIT);
        }

        boolean isReachMaxLimit = productService.isUserReachMaxApplyLimit(userCode);
        if (isReachMaxLimit) {
            throw new ApplicationException(OrderRestErrorEnum.REACH_MAX_APPLY_LIMIT);
        }


//        LOGGER.info("== 产品白名单 判断 ==,mobile:{}，productCategory:{}", mobile, productCategory.getCode());
//        Response<Boolean> whiteUser = tradeQueryService.isWhiteUser(mobile, 1, productCategory.getCode());
//        LOGGER.info("== 产品白名单 判断 ==,mobile:{}，productCategory:{},res:{}", mobile, productCategory.getCode(), whiteUser.getData());
//        if (!whiteUser.getData()) {
//            throw new ApplicationException("only VIP has access for this product.");
//        }

        return new ApiResponse<>(orderFilterResponse);
    }

    /**
     * 借款 下单
     *
     * @param productVO
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/submit/post", method = RequestMethod.POST)
    public ApiResponse<OrderInfoVO> add(HttpServletRequest request, @RequestBody @Valid ProductVO productVO) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        String channelCode = RequestLocalInfo.getRequestBasicInfo().getChannel();
        String appClient = RequestLocalInfo.getRequestBasicInfo().getAppClient();
        String userOrderSubmitPostLock = RedisKeyConsts.USER_ORDER_SUBMIT_POST_LOCK + userCode + productVO.getMerchantCode();
        if (apolloConfigUtil.getCheckProOpenByPackage()) {
            if (RequestLocalInfo.getRequestBasicInfo().getPackageName().equals("com.kly.cm.mall") && !productVO.getProductCode().equals("RupeeGo") && RequestLocalInfo.getRequestBasicInfo().getVersionCode() >= 14) {
                OrderInfoVO orderInfoVO = new OrderInfoVO();
                orderInfoVO.setSuccessMsg("Profile ready! Download the Pro version for faster audit.");
                orderInfoVO.setSuccessUrl("URL/External/https://dc2-api.rupee-mama.in/website/promotion/init?userCode=+" + userCode + "&jumpUrl=https://bit.ly/3dUJyxi");
                return new ApiResponse<>(orderInfoVO);
            }
        }


        Object o = redisClient.get(userOrderSubmitPostLock);
        if (o != null) {
            LOGGER.info("====== create order repeat, userCode:{} ======", userCode);
            throw new ApplicationException("Order is processing now, please wait.");
        }
        redisClient.set(userOrderSubmitPostLock, userCode, TimeConsts.ONE_MINUTE);

        try {
            Response<Product> productDetail = productFacade.getProductDetail(productVO.getProductCode(), false);
            if (productDetail.getData() == null) {
                throw new ApplicationException(ProductErrorCodeEnum.PRODUCT_NOT_EXIST);
            }
            String productCategory = productDetail.getData().getProductCategory().getCode();
            orderService.checkProfileStatus(userCode);
            String ip = HttpUtil.getIpAddr(request);
            Response<CreateTradeResponse> tradeResponseResponse = orderService.createOrderInfo(productVO.getMerchantCode(), userCode, productVO.getProductCode(), productCategory, channelCode, appClient, productVO.getUsageOfLoan(), ip);
            orderService.addWifiInfo(userCode, UserWifiVO.transfer2UserWifiVO(productVO.getCurrentWifi()), UserWifiVO.transfer2UserWifiVO(productVO.getNearbyWifis()));
            OrderInfoVO orderInfoVO = new OrderInfoVO();
            orderInfoVO.setTradeNo(tradeResponseResponse.getData().getTradeNo());
            orderInfoVO.setSuccessTitle(productDetail.getData().getProductCategory().getName() + " received your application");
            orderInfoVO.setSuccessMsg("Timely repayment can unlock more high-quality products!!");
            return new ApiResponse<>(orderInfoVO);
        } catch (ApplicationException applicationException) {
            LOGGER.error("====== create order exception, userCode:{} ,message:{}======", userCode, applicationException.getMessage());
            throw applicationException;
        } catch (Exception e) {
            LOGGER.error("====== create order exception, userCode:{} ======", userCode, e);
            throw new ApplicationException("Order processing exception.");
        } finally {
            redisClient.del(userOrderSubmitPostLock);
        }
    }

    /**
     * 订单详情页
     *
     * @param orderDetailRequest
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    public ApiResponse<OrderDetailVO> orderDetail(@RequestBody @Valid OrderDetailRequest orderDetailRequest) {
        OrderDetail orderDetail = orderService.getOrderDetailInfo(orderDetailRequest.getTradeNo());
        return new ApiResponse<>(new OrderDetailVO(orderDetail));
    }

    /**
     * 订单列表
     *
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public ApiResponse<RepaymentRecordsResponse> payment(@RequestBody @Valid OrderRecordRequest orderRecordRequest) {

        RepaymentRecordsVO repaymentRecords = orderService.orderList(orderRecordRequest.getType(), orderRecordRequest.getCurrentPage());
        return new ApiResponse<>(new RepaymentRecordsResponse(repaymentRecords));
    }

    /**
     * mobikwik支持的网上银行列表
     */
    @RequestMapping(value = "/netbank/list", method = RequestMethod.POST)
    public ApiResponse<List<NetBankItemVO>> getMobikwikNetBankList() {
        MobikwikNetBankEnum[] values = MobikwikNetBankEnum.values();
        ArrayList<NetBankItemVO> netBankItemVOS = new ArrayList<>();
        for (MobikwikNetBankEnum value : values) {
            NetBankItemVO netBankItemVO = new NetBankItemVO(value.getCode(), value.getName());
            netBankItemVOS.add(netBankItemVO);
        }
        return new ApiResponse<>(netBankItemVOS);
    }

    /**
     * 订单 提现
     *
     * @param request
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/withdraw/post", method = RequestMethod.POST)
    public ApiResponse<OrderInfoVO> withdraw(@RequestBody OrderWithdrawRequest request) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        String lockKey = RedisClient.format(RedisKeyConsts.USER_ORDER_WITHDRAW_POST_LOCK, userCode);
        Object o = redisClient.get(lockKey);
        if (o != null) {
            LOGGER.info("提现防并发,userCode:{}", userCode);
            throw new ApplicationException("Order is processing now, please wait.");
        }
        redisClient.set(lockKey, userCode, TimeConsts.TEN_MINUTES);
        try {
            orderService.withdraw(request.getTradeNo());
            return new ApiResponse<>("Withdrawal successful, transferring...");
        } finally {
            redisClient.del(lockKey);
        }
    }

    /**
     * 获取会员服务费信息
     *
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/service/info", method = RequestMethod.POST)
    public ApiResponse<ServiceFeeInfoResponse> serviceInfo() {
        ServiceFeeInfoResponse serviceFeeInfoResponse = orderService.serviceInfo();
        return new ApiResponse<>(serviceFeeInfoResponse);
    }

    /**
     * 支付服务费
     *
     * @param request
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/service/post", method = RequestMethod.POST)
    public ApiResponse<ServiceFeeResponse> servicePayment(@RequestBody @Valid ServiceFeeRequest request) {
        ServiceFeeResponse serviceFeeResponse = orderService.servicePayment(request.getPayAmount());
        return new ApiResponse<>(serviceFeeResponse);
    }

    /**
     * 查询平台服务费支付状态
     *
     * @param request
     * @return
     */
    @ParamsValidate
    @RequestMapping(value = "/service/query", method = RequestMethod.POST)
    public ApiResponse<ServiceFeeQueryResponse> serviceQuery(@RequestBody @Valid ServiceFeeQuery request) {
        ServiceFeeQueryResponse serviceFeeQueryResponse = orderService.serviceQuery(request.getServiceNo());
        return new ApiResponse<>(serviceFeeQueryResponse);
    }

}
